﻿using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Xml.Serialization;
using System.Collections.Generic;
using BeIT.MemCached;

namespace Chenxin.Lib.Cache
{
    public class CacheService
    {
        public enum xCacheType { Allways = 0, Period = 1, Today = 2, NoCache = 3 };

        /*cache items*/
        public MemcachedClient _mcInstance;


        #region properties

        private string _connectionString = "InstanceName=chenxin.com;ServerList=200.192.0.5;SendReceiveTimeout=5000;MinPoolSize=1;MaxPoolSize=500;Enabled=True";
        /// <summary>
        /// 链接字符串
        /// </summary>
        public string ConnectionString
        {
            get { return _connectionString; }
        }
        private string _instancename;
        /// <summary>
        /// 缓存实例名
        /// </summary>
        public string InstanceName
        {
            get { return _instancename; }
        }
        private string _serverlist;
        /// <summary>
        /// 缓存服务器列表
        /// </summary>
        public string ServerList
        {
            get { return _serverlist; }
        }
        private int _sendreceivetimeout;
        /// <summary>
        /// 超时
        /// </summary>
        public int SendReceiveTimeout
        {
            get { return _sendreceivetimeout; }
        }
        private uint _minPoolSize;
        /// <summary>
        /// 最小缓存池大小
        /// </summary>
        public uint MinPoolSize
        {
            get { return _minPoolSize; }
        }
        private uint _maxpoolsize;
        /// <summary>
        /// 最大缓存池大小
        /// </summary>    
        public uint Maxpoolsize
        {
            get { return _maxpoolsize; }
        }
        private bool _enabled = false;
        /// <summary>
        /// 是否启用缓存服务
        /// </summary>
        public bool Enabled
        {
            get { return _enabled; }
        }
        private bool _hit = false;
        /// <summary>
        /// 是否命中
        /// </summary>
        public bool Hit
        {
            get { return _hit; }
        }
        #endregion


        /// <summary>
        /// 构造函数（兼容以前该类的构造方法）
        /// </summary>
        public CacheService(string conn)
        {
            InitCacheService(conn);
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public CacheService(Cache.CacheConn.xCacheConn cacheType)
        {
            string conn = new CacheConn().GetCacheConn(cacheType);
            InitCacheService(conn);
        }

        /// <summary>
        /// 初始化类信息
        /// </summary>
        private void InitCacheService(string conn)
        {
            _connectionString = conn;
            GetSettings();
            _mcInstance = GetInstance();
        }

        /// <summary>
        /// 设置参数
        /// </summary>
        private void GetSettings()
        {
            foreach (string strData in _connectionString.Split(';'))
            {
                string[] strArgs = strData.Split('=');
                if (strArgs.Length < 2) continue;
                string strKey = strArgs[0];
                string strValue = strArgs[1];

                switch (strKey.ToLower())
                {
                    case "instancename":
                        _instancename = strValue;
                        break;
                    case "serverlist":
                        _serverlist = strValue;
                        break;
                    case "sendreceivetimeout":
                        _sendreceivetimeout = int.Parse(strValue);
                        break;
                    case "minpoolsize":
                        _minPoolSize = uint.Parse(strValue);
                        break;
                    case "maxpoolsize":
                        _maxpoolsize = uint.Parse(strValue);
                        break;
                    case "enabled":
                        _enabled = bool.Parse(strValue);
                        break;
                }
            }
        }

        /// <summary>
        /// 获取缓存实例
        /// </summary>
        /// <returns>缓存实例</returns>
        private MemcachedClient GetInstance()
        {
            MemcachedClient cache = null;
            if (MemcachedClient.Exists(_instancename) == false)
            {
                MemcachedClient.Setup(_instancename, _serverlist.Split(','));
            }

            cache = MemcachedClient.GetInstance(_instancename);

            cache.SendReceiveTimeout = _sendreceivetimeout;
            cache.MinPoolSize = _minPoolSize;
            cache.MaxPoolSize = _maxpoolsize;
            return cache;
        }

        /// <summary>
        /// 设置缓存数据,可过期
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="expireTime">有效时间(分钟)</param>
        public void Set(string key, object value, int expireTime)
        {
            key = this.MakeMD5(key);
            if (expireTime < 0)
            {
                return;
            }
            if (expireTime == 0)
            {
                _mcInstance.Set(key, value);
            }
            if (expireTime > 0)
            {
                _mcInstance.Set(key, value, System.DateTime.Now.AddMinutes(expireTime));
            }
        }

        /// <summary>
        /// 设置缓存数据,可过期
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="expireDateTime">截止时间</param>
        public void Set(string key, object value, DateTime expireDateTime)
        {
            key = this.MakeMD5(key);
            if (expireDateTime < DateTime.Now)
            {
                return;
            }
            if (expireDateTime >= DateTime.Now)
            {
                _mcInstance.Set(key, value, expireDateTime);
            }
        }

        /// <summary>
        /// 设置缓存数据,不过期
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        public void Set(string key, object value)
        {
            Set(key, value, 0);
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>返回对象</returns>
        public object GetObject(string key)
        {
            key = this.MakeMD5(key);
            object data = _enabled ? _mcInstance.Get(key) : null;
            _hit = (null != data);
            return data;
        }

        /// <summary>
        /// 获取DataSet
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>DataSet对象</returns>
        public System.Data.DataSet GetDataSet(string key)
        {
            object obj = GetObject(key);

            return obj as System.Data.DataSet;
        }

        /// <summary>
        /// 获取DataTable
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>DataTable对象</returns>
        public System.Data.DataTable GetDataTable(string key)
        {
            object obj = GetObject(key);

            return obj as System.Data.DataTable;
        }

        /// <summary>
        /// 获取DataRow
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>DataRow对象</returns>
        public System.Data.DataRow GetDataRow(string key)
        {
            object obj = GetObject(key);

            return obj as System.Data.DataRow;
        }

        /// <summary>
        /// 获取DataRow数组
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>DataRow数组</returns>
        public System.Data.DataRow[] GetDataRowArray(string key)
        {
            object obj = GetObject(key);

            return obj as System.Data.DataRow[];
        }

        /// <summary>
        /// 获取字符串
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>字符串</returns>
        public string GetString(string key)
        {
            object obj = GetObject(key);

            return (obj == null) ? null : obj.ToString();
        }

        /// <summary>
        /// 获取字符串数组
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>字符串数组</returns>
        public string[] GetStringArray(string key)
        {
            object obj = GetObject(key);

            return obj as string[];
        }

        /// <summary>
        /// 获取布尔泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>布尔值或null</returns>
        public bool? GetBool(string key)
        {
            object obj = GetObject(key);

            return Convert.ToBoolean(obj);
        }

        /// <summary>
        /// 获取byte泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>byte类型值或null</returns>
        public byte? GetByte(string key)
        {
            object obj = GetObject(key);

            return Convert.ToByte(obj);
        }

        /// <summary>
        /// 获取short泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>short类型值或null</returns>
        public short? GetInt16(string key)
        {
            object obj = GetObject(key);

            return Convert.ToInt16(obj);
        }

        /// <summary>
        ///  获取int泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>int类型值或null</returns>
        public int? GetInt32(string key)
        {
            object obj = GetObject(key);

            return Convert.ToInt32(obj);
        }

        /// <summary>
        /// 获取long泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>long类型值或null</returns>
        public long? GetInt64(string key)
        {
            object obj = GetObject(key);

            return Convert.ToInt64(obj);
        }

        /// <summary>
        /// 获取float泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>float类型值或null</returns>
        public float? GetFloat(string key)
        {
            object obj = GetObject(key);

            return (obj == null) ? (float?)null : float.Parse(obj.ToString());
        }

        /// <summary>
        /// 获取double泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>double类型值或null</returns>
        public double? GetDouble(string key)
        {
            object obj = GetObject(key);

            return Convert.ToDouble(obj);
        }

        /// <summary>
        /// 获取decimal泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>decimal类型值或null</returns>
        public decimal? GetDecimal(string key)
        {
            object obj = GetObject(key);

            return Convert.ToDecimal(obj);
        }

        /// <summary>
        /// 获取Guid泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>Guid类型值或null</returns>
        public Guid? GetGuid(string key)
        {
            object obj = GetObject(key);

            return (obj == null) ? (Guid?)null : new Guid(obj.ToString());
        }

        /// <summary>
        /// 获取DateTime泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>DateTime类型值或null</returns>
        public DateTime? GetDateTime(string key)
        {
            object obj = GetObject(key);

            return Convert.ToDateTime(obj);
        }

        /// <summary>
        /// 获取List泛型对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>List类型值或null</returns>
        public List<T> GetList<T>(string key)
        {
            object obj = GetObject(key);

            return obj as List<T>;
        }

        /// <summary>
        /// 获取特定类型的对象
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>返回对象</returns>
        public T GetObject<T>(string key)
        {
            object obj = GetObject(key);

            return (T)obj;
        }

        /// <summary>
        /// 删除缓存对象
        /// </summary>
        /// <param name="key">键</param>
        public void Delete(string key)
        {
            key = this.MakeMD5(key);
            this._mcInstance.Delete(key);
        }

        /// <summary>
        /// 设置计数器
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        public void SetCounter(string key, ulong value)
        {
            key = this.MakeMD5(key);
            this._mcInstance.SetCounter(key, value);
        }

        /// <summary>
        /// 获取计数器
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        public ulong? GetCounter(string key)
        {
            key = this.MakeMD5(key);
            ulong? value = this._mcInstance.GetCounter(key);
            _hit = (value.HasValue);
            return value;
        }

        /// <summary>
        /// 缓存对象自增长
        /// </summary>
        /// <param name="key">键</param>
        public ulong? Increment(string key)
        {
            return Increment(key, 1);
        }

        /// <summary>
        /// 缓存对象自增长
        /// </summary>
        /// <param name="key">键</param>
        public ulong? Increment(string key, ulong value)
        {
            key = this.MakeMD5(key);
            return this._mcInstance.Increment(key, value);
        }

        /// <summary>
        /// 缓存对象自减
        /// </summary>
        /// <param name="key">键</param>
        public ulong? Decrement(string key)
        {
            return Decrement(key, 1);
        }

        /// <summary>
        /// 缓存对象自减
        /// </summary>
        /// <param name="key">键</param>
        public ulong? Decrement(string key, ulong value)
        {
            key = this.MakeMD5(key);
            return this._mcInstance.Decrement(key, value);
        }

        /// <summary>
        /// 对KEY进行MD5编码
        /// </summary>
        /// <param name="SrcStr"></param>
        /// <returns></returns>
        private string MakeMD5(string key)
        {
            key = key.ToLower();
            string MD5 = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "md5");

            return MD5;
        }
    }
}
